package pl.edu.agh.iosr.gamblingzone.commons;

import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

import javax.ejb.Remove;
import javax.ejb.Stateful;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Create;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Logger;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.Startup;
import org.jboss.seam.log.Log;

import pl.edu.agh.iosr.gamblingzone.dao.AbstractEventDAO;
import pl.edu.agh.iosr.gamblingzone.dao.DisciplineDAO;
import pl.edu.agh.iosr.gamblingzone.dao.GroupDAO;
import pl.edu.agh.iosr.gamblingzone.dao.ParticipantDAO;
import pl.edu.agh.iosr.gamblingzone.dao.UserDAO;
import pl.edu.agh.iosr.gamblingzone.model.AbstractEvent;
import pl.edu.agh.iosr.gamblingzone.model.Bet;
import pl.edu.agh.iosr.gamblingzone.model.BettingSlip;
import pl.edu.agh.iosr.gamblingzone.model.Discipline;
import pl.edu.agh.iosr.gamblingzone.model.Group;
import pl.edu.agh.iosr.gamblingzone.model.MoneyVoucher;
import pl.edu.agh.iosr.gamblingzone.model.Participant;
import pl.edu.agh.iosr.gamblingzone.model.User;
import pl.edu.agh.iosr.gamblingzone.utils.DAOFactory;
import pl.edu.agh.iosr.gamblingzone.utils.EJBDAOFactoryBean;

/**
 * The Class DataGeneratorBean.
 */
@Name("dataGenerator")
@Scope(ScopeType.APPLICATION)
@Stateful
@Startup
public class DataGeneratorBean implements DataGenerator {

	/** The entity manager. */
	@PersistenceContext
	EntityManager entityManager;

	/** The dao. */
	@In(required=true)
	DAOFactory dao;

	/** The log. */
	@Logger
	Log log;

	/* (non-Javadoc)
	 * @see pl.edu.agh.iosr.gamblingzone.commons.DataGenerator#generateData()
	 */
	@Create
	public void generateData() {
		
		if (dao == null) {
			dao = new EJBDAOFactoryBean();
		}

		generateParticipants();
		generateDisciplinesGroupsEvents();
		generateEvents();
		generateUsers();
		generateTempBettingSlips();
		generateBettingSlips();
		generateBets();
		generateMoneyVoucher();
	}



	/**
	 * Generate events.
	 */
	public void generateEvents() {
		GroupDAO groupDAO = dao.getGroupDAO();
		ParticipantDAO participantDAO =  dao.getParticipantDAO();

		List<Participant> participants = participantDAO.findAll();
		Random randomGenerator = new Random();

		for(Group g: groupDAO.findAll()) {
			
			for (int i = 0; i < 5; i++) {
				AbstractEvent ae = new AbstractEvent();
				ae.setClosingDate(new Date());

				int rand = Math.abs(randomGenerator.nextInt(participants.size()));
				Participant p1 = participants.get(rand);
				Participant p2 = null;
				do {
					rand = Math.abs(randomGenerator.nextInt(participants.size()));
					p2 = participants.get(rand);
				} while(p2.getName().equals(p1.getName()));

				ae.addParticipant(p1, Math.random());
				ae.addParticipant(p2, Math.random());
				g.addEvent(ae);
			}
		}

		entityManager.flush();
	}

	/**
	 * Generate disciplines groups events.
	 */
	public void generateDisciplinesGroupsEvents() {

		DisciplineDAO disciplineDAO = dao.getDisciplineDAO();

		List<String> disciplineNames = new LinkedList<String>();
		List<String> groupNames = new LinkedList<String>();

		disciplineNames.add("Pilka nozna");
		disciplineNames.add("Siatkowka");
		disciplineNames.add("Hokej");
		disciplineNames.add("Koszykowka");
		disciplineNames.add("Pilka reczna");
		disciplineNames.add("Tenis");
		disciplineNames.add("Hokej");
		disciplineNames.add("Baseball");
		disciplineNames.add("Fromula 1");
		disciplineNames.add("Boks");
		disciplineNames.add("Rugby");
		disciplineNames.add("Piłka halowa");
		disciplineNames.add("Snooker");
		disciplineNames.add("Golf");
		disciplineNames.add("Skoki narciarskie");
		

		groupNames.add("Pierwsza liga");
		groupNames.add("Druga liga");
		groupNames.add("Trzecia liga");
		groupNames.add("Puchar");

		// disciplines
		for(String d: disciplineNames) {
			Discipline tmpDiscipline = new Discipline();
			tmpDiscipline.setName(d);
			tmpDiscipline.setDescription(d);

			// groups
			for(String g: groupNames) {
				Group tmpGroup = new Group();
				tmpGroup.setName(g);
				tmpGroup.setDescription(g);

				tmpDiscipline.addGroup(tmpGroup);
			}

			disciplineDAO.makePersistent(tmpDiscipline);
		}

		entityManager.flush();
	}

	/**
	 * Generate participants.
	 */
	public void generateParticipants() {
		ParticipantDAO participantDAO = dao.getParticipantDAO();

		List<String> participantNames = new LinkedList<String>();

		participantNames.add("Wisla Krakow");
		participantNames.add("Legia Warszaw");
		participantNames.add("Belchatow");
		participantNames.add("Lech Posnan");
		participantNames.add("Zaglebie Lubin");
		participantNames.add("Jagiellonia Bialystok");
		participantNames.add("Groclin");
		participantNames.add("Ruch Chorzow");
		participantNames.add("Odra Wodzislaw");
		participantNames.add("Korona Kielce");
		participantNames.add("Widzew Lodz");
		participantNames.add("Gornik Zabrze");
		participantNames.add("LKS");
		participantNames.add("Polonia Bytom");
		participantNames.add("Cracovia");
		participantNames.add("Zaglebie");
		participantNames.add("Sosnowiec");
//		participantNames.add("");
//		participantNames.add("");
//		participantNames.add("");
//		participantNames.add("");
//		participantNames.add("");
//		participantNames.add("");
//		participantNames.add("");
//		participantNames.add("");
//		participantNames.add("");
//		participantNames.add("");
//		participantNames.add("");
//		participantNames.add("");
//		participantNames.add("");
//		participantNames.add("");
//		participantNames.add("");
//		participantNames.add("");
//		participantNames.add("");
//		participantNames.add("");
//		participantNames.add("");
//		participantNames.add("");
//		participantNames.add("");
//		participantNames.add("");
//		participantNames.add("");
//		participantNames.add("");

		Random randomGenerator = new Random();
		for (int i = 0; i < participantNames.size(); i++) {
			Participant tmpParticipant = new Participant();
			int rand = randomGenerator.nextInt(participantNames.size());
			tmpParticipant.setName(participantNames.get(rand));
			tmpParticipant.setDescription("blah blah");

			participantDAO.makePersistent(tmpParticipant);
		}

		entityManager.flush();
	}

	/**
	 * Generate users.
	 */
	public void generateUsers() {
		UserDAO userDAO = dao.getUserDAO();

		List<String> names = new LinkedList<String>();

		names.add("Albert Einstein");
		names.add("Albert Fert ");
		names.add("Peter Grünberg");
		names.add("John C. Mather ");
		names.add("George F. Smoot");
		names.add("Roy J. Glauber ");
		names.add("John L. Hall ");
		names.add("Theodor W. Hänsch");
		names.add("David J. Gross ");
//		names.add("H. David Politzer ");
//		names.add("Frank Wilczek");
//		names.add("Alexei A. Abrikosov ");
//		names.add("Vitaly L. Ginzburg ");
//		names.add("Anthony J. Leggett");
//		names.add("Raymond Davis Jr. ");
//		names.add("Masatoshi Koshiba ");
//		names.add("Riccardo Giacconi");
//		names.add("Eric A. Cornell ");
//		names.add("Wolfgang Ketterle ");
//		names.add("Carl E. Wieman");
//		names.add("Zhores I. Alferov ");
//		names.add("Herbert Kroemer ");
//		names.add("Jack S. Kilby");
//		names.add("Gerardus 't Hooft ");
//		names.add("Martinus J.G. Veltman");
//		names.add("Robert B. Laughlin ");
//		names.add("Horst L. Störmer ");
//		names.add("Daniel C. Tsui");
//		names.add("Steven Chu ");
//		names.add("Claude Cohen-Tannoudji ");
//		names.add("William D. Phillips");
//		names.add("David M. Lee ");
//		names.add("Douglas D. Osheroff ");
//		names.add("Robert C. Richardson");
//		names.add("Martin L. Perl ");
//		names.add("Frederick Reines");
//		names.add("Bertram N. Brockhouse ");
//		names.add("Clifford G. Shull");
//		names.add("Russell A. Hulse ");
//		names.add("Joseph H. Taylor Jr.");
//		names.add("Georges Charpak");
//		names.add("Pierre-Gilles de Gennes");
//		names.add("Jerome I. Friedman ");
//		names.add("Henry W. Kendall ");
//		names.add("Richard E. Taylor");
//		names.add("Norman F. Ramsey ");
//		names.add("Hans G. Dehmelt ");
//		names.add("Wolfgang Paul");
//		names.add("Leon M. Lederman ");
//		names.add("Melvin Schwartz ");
//		names.add("Jack Steinberger");
//		names.add("J. Georg Bednorz ");
//		names.add("K. Alex Müller");
//		names.add("Ernst Ruska ");
//		names.add("Gerd Binnig ");
//		names.add("Heinrich Rohrer");
//		names.add("Klaus von Klitzing");
//		names.add("Carlo Rubbia ");
//		names.add("Simon van der Meer");
//		names.add("Subramanyan Chandrasekhar ");
//		names.add("William A. Fowler");
//		names.add("Kenneth G. Wilson");
//		names.add("Nicolaas Bloembergen ");
//		names.add("Arthur L. Schawlow ");
//		names.add("Kai M. Siegbahn");
//		names.add("James Cronin ");
//		names.add("Val Fitch");
//		names.add("Sheldon Glashow ");
//		names.add("Abdus Salam ");
//		names.add("Steven Weinberg");
//		names.add("Pyotr Kapitsa ");
//		names.add("Arno Penzias ");
//		names.add("Robert Woodrow Wilson");
//		names.add("Philip W. Anderson ");
//		names.add("Sir Nevill F. Mott ");
//		names.add("John H. van Vleck");
//		names.add("Burton Richter ");
//		names.add("Samuel C.C. Ting");
//		names.add("Aage N. Bohr ");
//		names.add("Ben R. Mottelson ");
//		names.add("James Rainwater");
//		names.add("Martin Ryle ");
//		names.add("Antony Hewish");
//		names.add("Leo Esaki ");
//		names.add("Ivar Giaever ");
//		names.add("Brian D. Josephson");
//		names.add("John Bardeen ");
//		names.add("Leon N. Cooper ");
//		names.add("Robert Schrieffer");
//		names.add("Dennis Gabor");
//		names.add("Hannes Alfvén ");
//		names.add("Louis Néel");
//		names.add("Murray Gell-Mann");
//		names.add("Luis Alvarez");
//		names.add("Hans Bethe");
//		names.add("Alfred Kastler");
//		names.add("Sin-Itiro Tomonaga ");
//		names.add("Julian Schwinger ");
//		names.add("Richard P. Feynman");
//		names.add("Charles H. Townes ");
//		names.add("Nicolay G. Basov ");
//		names.add("Aleksandr M. Prokhorov");
//		names.add("Eugene Wigner ");
//		names.add("Maria Goeppert-Mayer ");
//		names.add("J. Hans D. Jensen");
//		names.add("Lev Landau");
//		names.add("Robert Hofstadter ");
//		names.add("Rudolf Mössbauer");
//		names.add("Donald A. Glaser");
//		names.add("Emilio Segrè ");
//		names.add("Owen Chamberlain");
//		names.add("Pavel A. Cherenkov ");
//		names.add("Il´ja M. Frank ");
//		names.add("Igor Y. Tamm");
//		names.add("Chen Ning Yang ");
//		names.add("Tsung-Dao Lee");
//		names.add("William B. Shockley ");
//		names.add("John Bardeen ");
//		names.add("Walter H. Brattain");
//		names.add("Willis E. Lamb ");
//		names.add("Polykarp Kusch");
//		names.add("Max Born ");
//		names.add("Walther Bothe");
//		names.add("Frits Zernike");
//		names.add("Felix Bloch ");
//		names.add("E. M. Purcell");
//		names.add("John Cockcroft ");
//		names.add("Ernest T.S. Walton");
//		names.add("Cecil Powell");
//		names.add("Hideki Yukawa");
//		names.add("Patrick M.S. Blackett");
//		names.add("Edward V. Appleton");
//		names.add("Percy W. Bridgman");
//		names.add("Wolfgang Pauli");
//		names.add("Isidor Isaac Rabi");
//		names.add("Otto Stern");
//		names.add("Ernest Lawrence");
//		names.add("Enrico Fermi");
//		names.add("Clinton Davisson ");
//		names.add("George Paget Thomson");
//		names.add("Victor F. Hess ");
//		names.add("Carl D. Anderson");
//		names.add("James Chadwick");
//		names.add("Erwin Schrödinger ");
//		names.add("Paul A.M. Dirac");
//		names.add("Werner Heisenberg");
//		names.add("Venkata Raman");
//		names.add("Louis de Broglie");
//		names.add("Owen Willans Richardson");
//		names.add("Arthur H. Compton ");
//		names.add("C.T.R. Wilson");
//		names.add("Jean Baptiste Perrin");
//		names.add("James Franck ");
//		names.add("Gustav Hertz");
//		names.add("Manne Siegbahn");
//		names.add("Robert A. Millikan");
//		names.add("Niels Bohr");
//		names.add("Albert Einstein");
//		names.add("Charles Edouard Guillaume");
//		names.add("Johannes Stark");
//		names.add("Max Planck");
//		names.add("Charles Glover Barkla");
//		names.add("William Bragg ");
//		names.add("Lawrence Bragg");
//		names.add("Max von Laue");
//		names.add("Heike Kamerlingh Onnes");
//		names.add("Gustaf Dalén");
//		names.add("Wilhelm Wien");
//		names.add("Johannes Diderik van der Waals");
//		names.add("Guglielmo Marconi ");
//		names.add("Ferdinand Braun");
//		names.add("Gabriel Lippmann");
//		names.add("Albert A. Michelson");
//		names.add("J.J. Thomson");
//		names.add("Philipp Lenard");
//		names.add("Lord Rayleigh");
//		names.add("Henri Becquerel ");
//		names.add("Pierre Curie ");
//		names.add("Marie Curie");
//		names.add("Hendrik A. Lorentz ");
//		names.add("Pieter Zeeman");
//		names.add("Wilhelm Conrad Röntgen");

		int i = 0;
		for(String u: names) {
			User tmpUser = new User();
			String name = u.split(" ")[0];
			tmpUser.setFirstName(name);
			tmpUser.setSurname(u.replaceAll(name, ""));
			tmpUser.setBirthDate(new Date());
			tmpUser.setEmail("alibaba@pl.pl");
			tmpUser.addRole("user");
			if (i == 2) tmpUser.addRole("admin");
			tmpUser.setLoginName("alibaba"+(i++));
			tmpUser.setPassword("abra33");
			tmpUser.setTempBettingSlip(new BettingSlip());

			userDAO.makePersistent(tmpUser);
		}

		entityManager.flush();
	}

	/**
	 * Generate temp betting slips.
	 */
	public void generateTempBettingSlips() {
		AbstractEventDAO abstractEventDAO = dao.getEventDAO();
		UserDAO userDAO = dao.getUserDAO();

		Random random = new Random();
		List<Integer> randList = new LinkedList<Integer>();

		List<AbstractEvent> abList = abstractEventDAO.findAll();

		for(User u: userDAO.findAll()) {
			BettingSlip bs = u.getTempBettingSlip();
			bs.setMoney(Math.abs(random.nextLong())%10000);

			// rand n integers
			while(randList.size() < Math.abs(random.nextInt(10)+2)) {
				randList.add(random.nextInt(abList.size()));
			}

			for(Integer i : randList) {
				AbstractEvent ae = abstractEventDAO.findAll().get(i);
				Bet tmpBet = new Bet();
				tmpBet.setWinner((Participant)ae.getRates().keySet().toArray()[0]);
				tmpBet.addEvent(ae);

				bs.addBet(tmpBet);
			}

			randList.clear();
		}

		entityManager.flush();
	}

	/**
	 * Generate betting slips.
	 */
	public void generateBettingSlips() {
		UserDAO userDAO = dao.getUserDAO();

		Random random = new Random();

		for(User u: userDAO.findAll()) {

			int numOfBettingSlips = Math.abs(random.nextInt(40)+10);

			for (int j = 0; j < numOfBettingSlips; j++) {

				BettingSlip bs = new BettingSlip();
				bs.setMoney(Math.abs(random.nextLong())%10000);
				bs.setWasPaid(true);

				u.addBettingSlip(bs);
			}
		}

		entityManager.flush();
	}

	/**
	 * Generate bets.
	 */
	public void generateBets() {
		UserDAO userDAO = dao.getUserDAO();
		AbstractEventDAO abstractEventDAO = dao.getEventDAO();

		Random random = new Random();
		List<Integer> randList = new LinkedList<Integer>();

		List<AbstractEvent> abList = abstractEventDAO.findAll();

		for(User u: userDAO.findAll()) {

			// through betting slips
			for (BettingSlip bs: u.getBettingSlips()) {

				bs.setMoney(Math.abs(random.nextLong())%10000);
				bs.setWasPaid(true);

				// rand n integers
				while(randList.size() < Math.abs(random.nextInt(10))+2) {
					randList.add(random.nextInt(abList.size()));
				}

				for(Integer i : randList) {
					AbstractEvent ae = abstractEventDAO.findAll().get(i);
					Bet tmpBet = new Bet();
					tmpBet.setWinner((Participant)ae.getRates().keySet().toArray()[0]);
					tmpBet.addEvent(ae);

					bs.addBet(tmpBet);
				}

				randList.clear();
			}		
		}

		entityManager.flush();
	}

	/**
	 * Generate money voucher.
	 */
	public void generateMoneyVoucher() {

		UserDAO userDAO = dao.getUserDAO();

		for (User user : userDAO.findAll()) {

			for(int i = 0; i < 15; i++) {
				MoneyVoucher voucher = new MoneyVoucher();
				voucher.setActive(false);
				voucher.setValue(1000L);
				voucher.setVoucherHash("5#@$^#@%$");
				voucher.setExpirationDate(new Date());				

				user.addVouchers(voucher);
			}
		}

		entityManager.flush();
	}

	/* (non-Javadoc)
	 * @see pl.edu.agh.iosr.gamblingzone.commons.DataGenerator#getEntityManager()
	 */
	public EntityManager getEntityManager() {
		return entityManager;
	}

	/* (non-Javadoc)
	 * @see pl.edu.agh.iosr.gamblingzone.commons.DataGenerator#setEntityManager(javax.persistence.EntityManager)
	 */
	public void setEntityManager(EntityManager em) {
		this.entityManager = em;
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#finalize()
	 */
	@Remove
	public void finalize() {

	}



	/**
	 * Gets the dao.
	 * 
	 * @return the dao
	 */
	public DAOFactory getDao() {
		return dao;
	}



	/**
	 * Sets the dao.
	 * 
	 * @param dao the new dao
	 */
	public void setDao(DAOFactory dao) {
		this.dao = dao;
	}
}
